#pragma once

#include "global.h"

namespace cppdt {

    template <typename TYPE>
    class SyncQueue {
    public:
        SyncQueue()
            : mWaits(0) {
        }

        virtual ~SyncQueue() {
        }

        size_t Enqueue(const TYPE& obj) {
            std::unique_lock<std::mutex> lock(mMutex);
            mList.push_back(obj);
            if (mWaits) {
                mCond.notify_one();
            }
            return mList.size();
        }

        bool Dequeue(TYPE& obj, int32_t msec) {
            std::unique_lock<std::mutex> lock(mMutex);
            if (mList.empty()) {
                ++mWaits;
                mCond.wait_for(lock, std::chrono::milliseconds(msec));
                --mWaits;
            }

            if (mList.empty())
                return false;

            obj = mList.front();
            mList.pop_front();
            return true;
        }

    private:
        SyncQueue(const SyncQueue&);
        SyncQueue& operator =(const SyncQueue&);

    protected:
        std::list<TYPE> mList;
        std::mutex mMutex;
        std::condition_variable mCond;
        size_t mWaits;
    };

}
